package ex01_commonsClass.class01_object;

import org.junit.Test;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 寒江醉月
 * @description: Java对象根类Object的分析
 * @date 2021/4/5 18:10
 */
public class ObjectAnalyze {


    @Test
    public void cloneType(){
        Student student = new Student();
        Teacher teacher = new Teacher("大大");
        student.setId(1);
        student.setName("小小");
        student.setTeacher(teacher);
        try {
            Student clone = (Student)student.clone();
            teacher.setName("嘿嘿");
            System.out.println(clone);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }


    @Test
     public void equalsWithSomething(){
        ArrayList<String> list = new ArrayList<>();
        list.add("hello");
        list.add("hello");
        list.add("world");
        printAddress(list);
    }


    /**
     * 打印对象地址和hashcode，
     */
    private void printAddress(List list){
        try {
            for (Object o : list) {
                System.out.println(o + "的内存地址：" + addressOf(o) + "," +
                        o + "的hashCode十六位无符号数：" + Integer.toHexString(o.hashCode()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 网上抄的获取对象内存地址的方法
     * @param o 对象
     * @return 对象地址
     */
    private long addressOf(Object o)  {
        Unsafe unsafe;
        long objectAddress = 0L;

        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);

            Object[] array = new Object[]{o};
            assert unsafe != null;
            long baseOffset = unsafe.arrayBaseOffset(Object[].class);
            //arrayBaseOffset方法是一个本地方法，可以获取数组第一个元素的偏移地址
            int addressSize = unsafe.addressSize();

            switch (addressSize) {
                case 4:
                    objectAddress = unsafe.getInt(array, baseOffset);
                    //getInt方法获取对象中offset偏移地址对应的int型field的值
                    break;
                case 8:
                    objectAddress = unsafe.getLong(array, baseOffset);
                    //getLong方法获取对象中offset偏移地址对应的long型field的值
                    break;
                default:
                    throw new Error("unsupported address size: " + addressSize);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return (objectAddress);
    }


}
